package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSearchDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.exam.QuestionDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.domain.query.PageQuery;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.InteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.InteractionReplyService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author 蒼飞
 * @since 2023-09-04
 */
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements InteractionQuestionService {

    private final UserClient userClient;
    private final SearchClient searchClient;
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;
    private final InteractionReplyMapper interactionReplyMapper;
    /**
     * 新增互动问题
     * @param questionFormDTO
     */
    @Override
    public void saveQuestion(QuestionFormDTO questionFormDTO) {
        //1.获取用户
        Long userId = UserContext.getUser();
        //2.封装VO
        InteractionQuestion question = BeanUtils.copyBean(questionFormDTO,InteractionQuestion.class);
        question.setUserId(userId);
        //3.保存
        this.save(question);
    }

    /**
     * 修改互动问题
     * @param questionFormDTO
     */
    @Override
    public void updateQuestion(Long id,QuestionFormDTO questionFormDTO) {
        LambdaUpdateWrapper<InteractionQuestion> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(InteractionQuestion::getId,id)
                .set(InteractionQuestion::getTitle,questionFormDTO.getTitle())
                .set(InteractionQuestion::getDescription,questionFormDTO.getDescription())
                .set(InteractionQuestion::getAnonymity,questionFormDTO.getAnonymity());
        this.update(wrapper);
    }


    /**
     * 分页查询互动问题
     * @param questionPageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryQuestionPage(QuestionPageQuery questionPageQuery) {
        //校验参数courseId
        Long courseId = questionPageQuery.getCourseId();
        Long sectionId = questionPageQuery.getSectionId();
        if(courseId == null && sectionId == null){
            throw new BadRequestException("课程id为空");
        }
        //获取登录用户
        Long userId = UserContext.getUser();
        //分页查询互动问题
        Page<InteractionQuestion> description = this.lambdaQuery()
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getProperty().equals("description"))//不查询description字段
                .eq(questionPageQuery.getOnlyMine(), InteractionQuestion::getUserId, userId)//查询自己的问题
                .eq(InteractionQuestion::getHidden, false)//管理员是否隐藏
                .eq(courseId != null, InteractionQuestion::getCourseId, questionPageQuery.getCourseId())
                .eq(sectionId != null, InteractionQuestion::getSectionId, questionPageQuery.getSectionId())
                .page(questionPageQuery.toMpPageDefaultSortByCreateTimeDesc());//分页,按创建时间排
        //查询的互动问题
        List<InteractionQuestion> records = description.getRecords();
        if(CollUtils.isEmpty(records)){
            return PageDTO.empty(description);
        }
        //根据最新回答id 批量查询回答信息
        List<Long> userIds = new ArrayList<>();//要查询的用户
        List<Long> answerIds = new ArrayList<>();//需要查询的最近一次互动回答id
        for(InteractionQuestion item:records){
            if(!item.getAnonymity()){ //只查询非匿名的问题
                userIds.add(item.getUserId());
            }
            answerIds.add(item.getLatestAnswerId());
        }
        answerIds.remove(null);//去除空的互动问题id
        //根据id查询最近一次回答
        Map<Long,InteractionReply> replyMap = new HashMap<>();
        if(!CollUtils.isEmpty(answerIds)){
            List<InteractionReply> interactionReplies = interactionReplyMapper.selectBatchIds(answerIds);
            for(InteractionReply item:interactionReplies){
                replyMap.put(item.getId(),item);
                //如果不是匿名
                if(!item.getAnonymity()){
                    userIds.add(item.getUserId());
                }
            }
        }
        //根据用户id查询用户信息
        userIds.remove(null);
        Map<Long, UserDTO> userMap = new HashMap<>();
        if(!CollUtils.isEmpty(userIds)){
            List<UserDTO> userDTOS = userClient.queryUserByIds(userIds);
            userMap = userDTOS.stream().collect(Collectors.toMap(UserDTO::getId,UserDTO -> UserDTO));
        }
        //封装
        List<QuestionVO> results = new ArrayList<>();
        for(InteractionQuestion item:records){
            QuestionVO questionVO = new QuestionVO();
            questionVO.setId(null);

            //如果不是匿名
            //封装提问者信息
            if(!item.getAnonymity()){
                //复制bean
                questionVO = BeanUtils.copyBean(item, QuestionVO.class);
                UserDTO userDTO = userMap.get(item.getUserId());
                questionVO.setUserId(userDTO.getId());
                questionVO.setUserName(userDTO.getName());
                questionVO.setUserIcon(userDTO.getIcon());
            }
            //最近一次回答信息
            InteractionReply interactionReply = replyMap.get(item.getLatestAnswerId());
            if(interactionReply != null){
                questionVO.setLatestReplyContent(interactionReply.getContent());
                //如果不是匿名
                if(!interactionReply.getAnonymity()){
                    questionVO.setLatestReplyUser(userMap.get(interactionReply.getUserId()).getName());
                }
            }
            results.add(questionVO);
        }
        return PageDTO.of(description,results);
    }

    /**
     * 根据id查询问题详情
     * @param id
     * @return
     */
    public QuestionVO queryQuestionById(Long id){
        //根据id查询问题
        InteractionQuestion interactionQuestion = this.getById(id);
        //校验数据 查询出问题为空或者隐藏
        if(interactionQuestion == null || interactionQuestion.getHidden()){
            return null;
        }
        QuestionVO questionVO = BeanUtils.copyBean(interactionQuestion, QuestionVO.class);
        //是否匿名
        if(!questionVO.getAnonymity()){
            UserDTO userDTO = userClient.queryUserById(questionVO.getUserId());
            if(userDTO != null){
                questionVO.setUserName(userDTO.getUsername());
                questionVO.setUserIcon(userDTO.getIcon());
            }
        }
        return questionVO;
    }

    /**
     * 删除互动问题
     * @param id
     */
    @Override
    public void deleteQuestion(Long id){
        //获取当前用户
        Long userId = UserContext.getUser();
        //查询当前问题是否存在
        InteractionQuestion interactionQuestion = this.getById(id);
        if(interactionQuestion == null){
            throw new BizIllegalException("问题不存在");
        }
        //判断是否是当前用户提问的
        if(!interactionQuestion.getUserId().equals(userId)){
            throw new BizIllegalException("问题不是当前用户提问的");
        }
        //删除问题
        baseMapper.deleteById(id);
        //删除问题下的回答和评论
        UpdateWrapper<InteractionReply> wrapper = new UpdateWrapper<>();
        wrapper.eq("question_id",id);
        interactionReplyMapper.delete(wrapper);
    }

    @Override
    public PageDTO<QuestionAdminVO> queryQuestionPageAdmin(QuestionAdminPageQuery query) {
        //通过feign远程调用search服务 根据课程名称模糊查询 返回课程id的list
        String courseName = query.getCourseName();
        List<Long> cIds = null;
        if(StringUtils.isNotBlank(courseName)){
             cIds = searchClient.queryCoursesIdByName(courseName);
            if (CollUtils.isEmpty(cIds)){//查询不到课程
                return PageDTO.empty(0L,0L);
            }
        }
        //根据课程id集合查询问题
        Integer status = query.getStatus();
        LocalDateTime beginTime = query.getBeginTime();
        LocalDateTime endTime = query.getEndTime();
        Page<InteractionQuestion> page = this.lambdaQuery()
                .in(cIds != null, InteractionQuestion::getId, cIds)
                .eq(status != null, InteractionQuestion::getStatus, status)
                .between(beginTime != null && endTime != null, InteractionQuestion::getCreateTime, beginTime, endTime)
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //获取records
        List<InteractionQuestion> records = page.getRecords();
        //获取id
        List<Long> userIds = new ArrayList<>();//用户id
        List<Long> courseIds = new ArrayList<>();//用户id
        List<Long> cataIds = new ArrayList<>();//章节id
        for (InteractionQuestion record:records){
            userIds.add(record.getUserId());
            courseIds.add(record.getCourseId());
            cataIds.add(record.getChapterId());
            cataIds.add(record.getSectionId());
        }
        //根据课程id查询课程名称
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        Map<Long, CourseSimpleInfoDTO> courseNameMap = new HashMap<>();
        if(CollUtils.isNotEmpty(courseList)){
            courseNameMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, CourseSimpleInfoDTO -> CourseSimpleInfoDTO));
        }
        //根据问题实体中问题所属章id 查询所属章节名
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //获取用户名
        List<UserDTO> users = userClient.queryUserByIds(userIds);
        Map<Long, String> userNameMap = new HashMap<>(users.size());
        if(CollUtils.isNotEmpty(users)){
            userNameMap = users.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }
        //po封装vo
        List<QuestionAdminVO> list = new ArrayList<>();
        for(InteractionQuestion record:records){
            QuestionAdminVO vo = BeanUtils.copyBean(record, QuestionAdminVO.class);
            list.add(vo);
            String username = userNameMap.get(record.getUserId());
            if (username != null){
                vo.setUserName(username);
            }
            CourseSimpleInfoDTO cInfoDTO = courseNameMap.get(record.getCourseId());
            if(cInfoDTO != null){
                vo.setCourseName(cInfoDTO.getName());
                vo.setCategoryName(categoryCache.getCategoryNames(cInfoDTO.getCategoryIds()));
            }
            vo.setChapterName(cataMap.getOrDefault(record.getChapterId(), ""));
            vo.setSectionName(cataMap.getOrDefault(record.getSectionId(), ""));
        }
        return PageDTO.of(page,list);
    }

    /**
     * 管理端隐藏问题
     * @param id
     * @param hidden
     */
    @Override
    public void hiddenQuestion(Long id, Boolean hidden) {
        //首先查询问题是否存在
        InteractionQuestion question = this.getById(id);
        if (question == null){
            throw new BizIllegalException("问题不存在");
        }
        //如果问题存在则隐藏问题
        LambdaUpdateChainWrapper<InteractionQuestion> set = this.lambdaUpdate()
                .eq(InteractionQuestion::getId, id)
                .set(hidden != null, InteractionQuestion::getHidden, hidden);
        set.update();

    }

    /**
     * 管理端查看问题详情
     * @param id
     * @return
     */
    @Override
    public QuestionAdminVO queryQuestionDetail(Long id) {
        //查询问题
        InteractionQuestion question = this.getById(id);
        if(question == null){
            throw new BizIllegalException("该问题不存在");
        }
        //获取提问者昵称
        UserDTO userDTO = userClient.queryUserById(question.getUserId());
        //获取课程名称
        CourseSearchDTO course = courseClient.getSearchInfo(question.getCourseId());
        //获取教师id
        Long teacherId = null;
        String courseName = null;
        List<Long> categoryIds = null;
        if(course != null){
            teacherId = course.getTeacher();
            courseName = course.getName();
            categoryIds = List.of(course.getCategoryIdLv1(),course.getCategoryIdLv2(), course.getCategoryIdLv3());
        }
        //获取教师名称
        UserDTO teacher = null;
        if(teacherId != null){
            teacher = userClient.queryUserById(teacherId);
        }
        //获取提问者名称
        Long userId = question.getUserId();
        UserDTO user = null;
        if(userId != null){
            user = userClient.queryUserById(userId);
        }
        //获取章节名称
        String categoryName = null;
        if (categoryIds != null){
            categoryName = categoryCache.getCategoryNames(categoryIds);
        }
        //封装VO
        QuestionAdminVO questionAdminVO = BeanUtils.copyBean(question, QuestionAdminVO.class);
        if (userDTO != null){
            questionAdminVO.setUserName(userDTO.getName());
        }
        //教师名称
        if(teacher != null){
            questionAdminVO.setTeacherName(teacher.getName());
        }
        //分类名称
        if (categoryName != null){
            questionAdminVO.setCategoryName(categoryName);
        }
        //提问者名称
        if (user != null){
            questionAdminVO.setUserName(user.getName());
        }
        List<Long> cataIds = new ArrayList<>();//章节id
        cataIds.add(question.getChapterId());
        cataIds.add(question.getSectionId());
        List<CataSimpleInfoDTO> catas = catalogueClient.batchQueryCatalogue(cataIds);
        Map<Long, String> cataMap = new HashMap<>(catas.size());
        if (CollUtils.isNotEmpty(catas)) {
            cataMap = catas.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }
        //章 节名称
        questionAdminVO.setChapterName(cataMap.getOrDefault(question.getChapterId(), ""));
        questionAdminVO.setSectionName(cataMap.getOrDefault(question.getSectionId(), ""));
        questionAdminVO.setCourseName(courseName);
        return questionAdminVO;
    }
}



